﻿using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;

namespace WebParser
{
    class Program
    {
        
        static void Main(string[] args)
        {
            //Get("http://172.16.17.97/cgi-bin/encoder?USER=Admin&PWD=123456&VIDEO_ENCODER=MJPEG");
            //Get("http://172.16.17.97/cgi-bin/system?USER=Admin&PWD=123456&RTP_B2=1");

            //UseHttpContent("172.16.17.97");
            //UseWebRequest("172.16.17.97");
            //UseWebRequest("192.168.1.2");            

            UseHttpContent("192.168.1.3");
            return;


            var header1 = Encoding.ASCII.GetBytes(@"
--boundary
Content-Type: video/mpeg4
Content-Length: 26986

");
            var header2 = Encoding.ASCII.GetBytes(@"
--boundary
Content-Type: video/mpeg4
Content-Length: 65535

");
            var header3 = Encoding.ASCII.GetBytes(@"
--boundary
Content-Type: video/mpeg4
Content-Length: 0

");
            var body1 = new byte[26986];
            var body2 = new byte[65535];
            var body3 = new byte[] {};
            Action<byte[]> init =
                b =>
                    {
                        for (var i = 0; i < b.Length; i++)
                            b[i] = 0xFF;
                    };
            init(body1);
            init(body2);
            init(body3);
            using (var mem = new MemoryStream())
            {
                for (var i = 0; i < 2000; i++)
                {
                    mem.Write(header3, 0, header3.Length);
                    mem.Write(body3, 0, body3.Length);

                    mem.Write(header1, 0, header1.Length);
                    mem.Write(body1, 0, body1.Length);
                
                    mem.Write(header2, 0, header2.Length);
                    mem.Write(body2, 0, body2.Length);

                    mem.Write(header3, 0, header3.Length);
                    mem.Write(body3, 0, body3.Length);
                }
                //Console.WriteLine("Parser1");
                //for (var i = 0; i < 10; i++)
                //{
                //    TestParser1(mem, "--boundary");
                //}
                //Console.WriteLine("Parser2");
                //for (var i = 0; i < 10; i++)
                //{
                //    TestParser2(mem, "--boundary");
                //}
                Console.WriteLine("Parser3");
                for (var i = 0; i < 10; i++)
                {
                    TestParser3(mem, "--boundary");
                }
                //TestParser2(mem, "--boundary");
            }
            Console.WriteLine("Done!");
            Console.ReadLine();
        }
        static bool CheckContent(ContentEventArgs e)
        {
            if (e.ContentType != "video/mpeg4") return false;
            if (e.ContentLength != e.Content.Length) return false;
            //for (var i = 0; i < e.ContentLength; i++)
            //    if (e.Content[i] != 0xFF) return false;
            return e.ContentLength == 26986 || e.ContentLength == 65535 || e.ContentLength == 0;
        }
        static void TestParser1(Stream stream, string boundary)
        {
            stream.Seek(0, SeekOrigin.Begin);
            var parser = new HttpContentParser1(boundary);
            var count = 0;
            parser.ContentReceived += (s, e) => count += CheckContent(e) ? 1 : 0;
            var buffer = new byte[0x2000];
            var timer = new Stopwatch();
            timer.Start();
            while (true)
            {
                var len = stream.Read(buffer, 0, buffer.Length);
                if (len < 1) break;
                for (var i = 0; i < len; i++)
                    parser.Parse(buffer[i]);
            }
            timer.Stop();
            Console.WriteLine("{0} ({1})", timer.ElapsedMilliseconds, count);
        }
        static void TestParser2(Stream stream, string boundary)
        {
            stream.Seek(0, SeekOrigin.Begin);
            var parser = new HttpContentParser(boundary);
            var count = 0;
            parser.ContentReceived += (s, e) => count += CheckContent(e) ? 1 : 0;
            var timer = new Stopwatch();
            timer.Start();
            while (stream.Position < stream.Length)
            {
                parser.Parse(stream);
            }
            timer.Stop();
            Console.WriteLine("{0} ({1})", timer.ElapsedMilliseconds, count);
        }
        static void TestParser3(Stream stream, string boundary)
        {
            var parser = new HttpContentParser(boundary);
            var count = 0;
            parser.ContentReceived += (s, e) => count += CheckContent(e) ? 1 : 0;
            var timer = new Stopwatch();
            timer.Start();
            for (var i = 0; i < 10; i++)
            {
                stream.Seek(0, SeekOrigin.Begin);
                while (stream.Position < stream.Length)
                    parser.Parse(stream);
            }
            timer.Stop();
            Console.WriteLine("{0} ({1})", timer.ElapsedMilliseconds, count);
        }
        private static void UseHttpContent(string ip)
        {
            var url = string.Format("http://{0}/cgi-bin/system?USER=Admin&PWD=123456&GET_STREAM", ip);
            var keepRunning = true;
            var w = new HttpContentServer();

            w.ContentReceived +=
                (s, e) => Console.WriteLine("{0}: {1} {2:ss}", e.ContentType, e.ContentLength, DateTime.Now);
            w.Error +=
                (s, e) =>
                {
                    Console.WriteLine(e.Exception.Message);
                    keepRunning = false;
                };
            w.Url = url;
            w.Method = "GET";
            w.Start();
            while (keepRunning)
            {
                var command = Console.ReadLine();
                if (string.IsNullOrEmpty(command)) continue;
                switch (command.ToLower())
                {
                    case "exit":
                        keepRunning = false;
                        break;
                    case "start":
                        w.Start();
                        break;
                    case "stop":
                        w.Stop();
                        break;
                    case "?":
                        Console.WriteLine(w.IsRunning ? "IsRunning" : "Idle");
                        break;
                }
            }
            w.Stop();
            while (w.IsRunning)
            {
                Console.Write(".");
                Thread.Sleep(100);
            }
        }
        private static void UseWebRequest(string ip)
        {
            var url = string.Format("http://{0}/cgi-bin/system?USER=Admin&PWD=123456&GET_STREAM", ip);
            var keepRunning = true;
            var w = new MimeReceiver();
            w.ContentReceived +=
                (s, e) => Console.WriteLine("{0}: {1}", e.ContentType, e.ContentLength);
            w.Error +=
                (s, e) =>
                    {
                        Console.WriteLine(e.Exception.Message);
                        keepRunning = false;
                    };
            w.Url = url;
            w.Method = "GET";
            //w.Start(url, "GET");
            w.Start();
            while (keepRunning)
            {
                var command = Console.ReadLine();
                if (string.IsNullOrEmpty(command)) continue;
                switch (command.ToLower())
                {
                    case "exit":
                        keepRunning = false;
                        break;
                    case "start":
                        //w.Start(url, "GET");
                        w.Start();
                        break;
                    case "stop":
                        w.Stop();
                        break;
                }
            }
            w.Stop();
            while (w.IsRunning)
            {
                Console.Write(".");
                Thread.Sleep(100);
            }
        }

        static string Get(string url)
        {
            var request = WebRequest.Create(url);
            var http = request as HttpWebRequest;
            if (http != null) http.AllowAutoRedirect = true;
            request.Proxy = null;
            request.Method = "GET";
            var response = request.GetResponse();
            if (response == null) throw new Exception("invalid response!");
            using (var s = response.GetResponseStream())
            {
                if (s == null) throw new Exception("invalid response stream!");
                using (var r = new StreamReader(s))
                {
                    return r.ReadToEnd();
                }
            }
        }
    }
}
